home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
basic
/
bwbasic.lha
/
bwbasic
/
bwb_exp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-12
|
40KB
|
1,576 lines
/****************************************************************
bwb_exp.c Expression Parser
for Bywater BASIC Interpreter
Copyright (c) 1992, Ted A. Campbell
Bywater Software
P. O. Box 4023
Duke Station
Durham, NC 27706
email: tcamp@acpub.duke.edu
Copyright and Permissions Information:
All U.S. and international copyrights are claimed by the
author. The author grants permission to use this code
and software based on it under the following conditions:
(a) in general, the code and software based upon it may be
used by individuals and by non-profit organizations; (b) it
may also be utilized by governmental agencies in any country,
with the exception of military agencies; (c) the code and/or
software based upon it may not be sold for a profit without
an explicit and specific permission from the author, except
that a minimal fee may be charged for media on which it is
copied, and for copying and handling; (d) the code must be
distributed in the form in which it has been released by the
author; and (e) the code and software based upon it may not
be used for illegal activities.
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "bwbasic.h"
#include "bwb_mes.h"
int exp_esc = 0; /* expression stack counter */
/***************************************************************
FUNCTION: bwb_exp()
DESCRIPTION: This is the function by which the expression
parser is called.
***************************************************************/
struct exp_ese *
bwb_exp( char *expression, int assignment, int *position )
{
struct exp_ese *rval; /* return value */
int entry_level, main_loop, adv_loop, err_condition;
char *e; /* pointer to current string */
int r; /* return value from functions */
register int c; /* quick counter */
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): expression <%s> assignment <%d> level <%d>",
& ( expression[ *position ] ), assignment, exp_esc );
bwb_debug( bwb_ebuf );
#endif
/* save the entry level of the expression stack in order to
check it at the end of this function */
entry_level = exp_esc;
err_condition = FALSE;
/* advance past whitespace or beginningg of line segment */
if ( expression[ *position ] == ':' )
{
++( *position );
}
adv_ws( expression, position );
if ( expression[ *position ] == ':' )
{
++( *position );
adv_ws( expression, position );
}
/* increment the expression stack counter to get a new level */
inc_esc();
/* check to be sure there is a legitimate expression
and set initial parameters for the main loop */
adv_loop = TRUE;
while( adv_loop == TRUE )
{
switch( expression[ *position ] )
{
case ' ': /* whitespace */
case '\t':
++(*position);
break;
case '\0': /* end of string */
case '\r':
case '\n':
main_loop = adv_loop = FALSE; /* break out of loop */
break;
default:
adv_loop = FALSE;
main_loop = TRUE;
exp_es[ exp_esc ].pos_adv = 0;
break;
}
}
/* main parsing loop */
while ( main_loop == TRUE )
{
/* set variable <e> to the start of the expression */
e = &( expression[ *position ] );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): main loop, level <%d> element <%s> ",
exp_esc, e );
bwb_debug( bwb_ebuf );
#endif
/* detect the operation required at this level */
exp_es[ exp_esc ].operation = exp_findop( e );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): exp_findop() returned <%d>",
exp_es[ exp_esc ].operation );
bwb_debug( bwb_ebuf );
#endif
/* perform actions specific to the operation */
switch( exp_es[ exp_esc ].operation )
{
case OP_ERROR:
main_loop = FALSE;
err_condition = TRUE;
break;
case OP_TERMINATE:
main_loop = FALSE;
/* *position += 1; */
dec_esc();
break;
case OP_STRJOIN: /* string join or tab */
case OP_STRTAB:
main_loop = FALSE;
dec_esc();
break;
case OP_ADD: /* in the case of any numerical operation, */
case OP_SUBTRACT:
case OP_MULTIPLY:
case OP_DIVIDE:
case OP_MODULUS:
case OP_EXPONENT:
case OP_INTDIVISION:
case OP_GREATERTHAN:
case OP_LESSTHAN:
case OP_GTEQ:
case OP_LTEQ:
case OP_NOTEQUAL:
case OP_NOT:
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_IMPLIES:
case OP_EQUIV:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): operator detected." );
bwb_debug( bwb_ebuf );
#endif
exp_es[ exp_esc ].pos_adv = -1; /* set to strange number */
/* cycle through operator table to find match */
for ( c = 0; c < N_OPERATORS; ++c )
{
if ( exp_ops[ c ].operation == exp_es[ exp_esc ].operation )
{
exp_es[ exp_esc ].pos_adv = strlen( exp_ops[ c ].symbol );
}
}
if ( exp_es[ exp_esc ].pos_adv == -1 ) /* was a match found? */
{
exp_es[ exp_esc ].pos_adv = 0; /* no -- set to 0 */
}
break; /* and move on */
case OP_EQUALS:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): equal sign detected." );
bwb_debug( bwb_ebuf );
#endif
if ( assignment == TRUE )
{
exp_es[ exp_esc ].operation = OP_ASSIGN;
}
exp_es[ exp_esc ].pos_adv = 1;
break;
case PARENTHESIS:
r = exp_paren( e );
break;
case CONST_STRING:
r = exp_strconst( e );
break;
case CONST_NUMERICAL:
r = exp_numconst( e );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): return from exp_numconst(), r = <%d>",
r );
bwb_debug( bwb_ebuf );
#endif
break;
case FUNCTION:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): calling exp_function(), expression <%s>",
e );
bwb_debug( bwb_ebuf );
#endif
r = exp_function( e );
break;
case VARIABLE:
r = exp_variable( e );
break;
default:
err_condition = TRUE;
main_loop = FALSE;
#if PROG_ERRORS
sprintf( bwb_ebuf, "in bwb_exp.c:bwb_exp(): unidentified operation (%d).",
exp_es[ exp_esc ].operation );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
break;
}
/* increment *position counter based on previous actions */
*position += exp_es[ exp_esc ].pos_adv;
exp_es[ exp_esc ].pos_adv = 0; /* reset advance counter */
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): advanced position; r <%d> err_c <%d>",
r, err_condition );
bwb_debug( bwb_ebuf );
#endif
#if INTENSIVE_DEBUG
if ( exp_es[ exp_esc ].operation == OP_EQUALS )
{
sprintf( bwb_ebuf, "in bwb_exp(): with OP_EQUALS: finished case" );
bwb_debug( bwb_ebuf );
}
#endif
/* check for end of string */
adv_loop = TRUE;
while( adv_loop == TRUE )
{
switch( expression[ *position ] )
{
case ' ': /* whitespace */
case '\t':
++(*position);
break;
case '\0': /* end of string */
case '\r':
case '\n':
case ':':
main_loop = adv_loop = FALSE; /* break out of loop */
break;
default:
adv_loop = FALSE;
break;
}
}
/* get a new stack level before looping */
if ( main_loop == TRUE )
{
r = inc_esc();
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): increment esc, r <%d>, err_c <%d>",
r, err_condition );
bwb_debug( bwb_ebuf );
#endif
}
/* check for error return */
if ( r == OP_ERROR )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): found r == OP_ERROR." );
bwb_debug( bwb_ebuf );
#endif
main_loop = FALSE;
err_condition = TRUE;
}
else
{
r = TRUE;
}
} /* end of main parsing loop */
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): breakout from main parsing loop, r <%d> err_c <%d>",
r, err_condition );
bwb_debug( bwb_ebuf );
#endif
/* check error condition */
if ( err_condition == TRUE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "ERROR: error detected in expression parser" );
bwb_debug( bwb_ebuf );
#endif
/* decrement the expression stack counter until it matches entry_level */
while( exp_esc > entry_level )
{
dec_esc();
}
}
/* no error; normal exit from function */
else
{
/* are any more operations needed? if we are still at entry level,
then they are not */
/* try operations */
exp_operation( entry_level );
/* see what is on top of the stack */
if ( exp_esc > ( entry_level + 1 ))
{
switch( exp_es[ exp_esc ].operation )
{
case OP_STRJOIN:
if ( exp_esc != ( entry_level + 2 ))
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in bwb_exp(): OP_STRJOIN in wrong position." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
}
break;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in bwb_exp(): incomplete expression." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
break;
}
/* decrement the expression stack counter */
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in bwb_exp(): before dec_esc type is <%c>",
exp_es[ exp_esc ].type );
bwb_debug( bwb_ebuf );
#endif
dec_esc();
}
/* assign rvar to the variable for the current level */
rval = &( exp_es[ exp_esc ] );
/* decrement the expression stack counter */
dec_esc();
/* check the current level before exit */
if ( entry_level != exp_esc )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in bwb_exp(): exit stack level (%d) does not match entry stack level (%d)",
exp_esc, entry_level );
bwb_error( bwb_ebuf );
#else
bwb_error( err_overflow );
#endif
}
}
/* return a pointer to the last stack level */
return rval;
}
/***************************************************************
FUNCTION: exp_findop()
DESCRIPTION: This function reads the expression to find
what operation is required at its stack level.
***************************************************************/
int
exp_findop( char *expression )
{
char *pointer; /* pointer to start of string */
register int c; /* character counter */
int carry_on; /* boolean: control while loop */
int rval; /* return value */
char tbuf[ MAXSTRINGSIZE + 1 ];
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_findop(): received <%s>", expression );
bwb_debug( bwb_ebuf );
#endif
/* set return value to OP_NULL initially */
rval = OP_NULL;
/* assign local pointer to expression to begin reading */
pointer = expression;
/* advance to the first significant character */
carry_on = TRUE;
while ( carry_on == TRUE )
{
switch( *pointer )
{
case ' ': /* whitespace */
case '\t':
++pointer; /* increment the pointer */
break; /* and move on */
default:
carry_on = FALSE; /* break out of while loop */
break;
}
}
/* we now have the first significant character and can begin parsing */
/* check the first character for an indication of a parenthetical
expression, a string constant, or a numerical constant that begins
with a digit (numerical constants beginning with a plus or minus
sign or hex/octal/binary constants will have to be detected by
exp_isnc() */
carry_on = TRUE;
switch ( *pointer )
{
case '\"': /* this should indicate a string constant */
rval = CONST_STRING;
break;
case '(': /* this will indicate a simple parenthetical expression */
rval = PARENTHESIS;
break;
case ':': /* terminate processing */
rval = OP_TERMINATE;
break;
case '0': /* these will indicate a numerical constant */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '&': /* designator for hex or octal constant */
rval = CONST_NUMERICAL;
break;
}
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_findop(): rval pos 1 is <%d>", rval );
bwb_debug( bwb_ebuf );
#endif
/* string constants, numerical constants, open parentheses, and
the plus and minus operators have been checked at this point;
but if the return value is still OP_NULL, other possibilities
must be checked, namely, other operators, function names, and
variable names */
/* get a character string to be interpreted */
if ( rval == OP_NULL )
{
carry_on = TRUE;
c = 0;
tbuf[ c ] = *pointer;
++c;
tbuf[ c ] = '\0';
while( carry_on == TRUE )
{
switch( pointer[ c ] )
{
case ' ': /* whitespace */
case '\t':
case '(':
case ')':
case ',':
case ';':
case '\0':
case '\n':
case '\r':
carry_on = FALSE;
break;
default:
tbuf[ c ] = pointer[ c ];
++c;
tbuf[ c ] = '\0';
break;
}
}
}
/* check for a BASIC command */
if ( rval == OP_NULL )
{
rval = exp_iscmd( tbuf );
}
/* check for numerical constant */
if ( rval == OP_NULL )
{
rval = exp_isnc( tbuf );
}
/* check for other operators */
if ( rval == OP_NULL )
{
rval = exp_isop( tbuf );
}
/* check for function name */
if ( rval == OP_NULL )
{
rval = exp_isfn( tbuf );
}
/* last: check for variable name, and assign it if there
is not already one */
if ( rval == OP_NULL )
{
rval = exp_isvn( tbuf );
}
/* return the value assigned (or OP_NULL if none assigned) */
return rval;
}
/***************************************************************
FUNCTION: exp_isnc()
DESCRIPTION: This function reads the expression to find
if a logical or mathematical operation is required at
this point.
***************************************************************/
int
exp_isnc( char *expression )
{
switch( expression[ 0 ] )
{
case '0': /* these will indicate a numerical constant */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '&': /* indicator for hex or octal constant */
return CONST_NUMERICAL;
case '+':
case '-':
/* if the previous stack level was a numerical value or a string,
then this is certainly not one; return OP_NULL here
and let the next function call to exp_isop() determine
the (plus or minus) operator */
if ( ( exp_es[ exp_esc - 1 ].operation == NUMBER )
|| ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
|| ( exp_es[ exp_esc - 1 ].operation == CONST_STRING ) )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isnc(): previous function is a number or string" );
bwb_debug( bwb_ebuf );
#endif
return OP_NULL;
}
/* similarly, if the previous stack level was a variable
with a numerical value (not a string), then this level
must be an operator, not a numerical constant */
if ( ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
&& ( exp_es[ exp_esc - 1 ].type != STRING ))
{
return OP_NULL;
}
/* failing these tests, the argument must be a numerical
constant preceded by a plus or minus sign */
return CONST_NUMERICAL;
default:
return OP_NULL;
}
}
/***************************************************************
FUNCTION: exp_isop()
DESCRIPTION: This function reads the expression to find
if a logical or mathematical operation is required at
this point.
This function presupposes that a numerical constant with
affixed plus or minus sign has been ruled out.
***************************************************************/
int
exp_isop( char *expression )
{
register int c; /* counter */
char tbuf[ MAXSTRINGSIZE + 1 ];
/* first convert the expression to upper-case so that comparisons
will work */
for ( c = 0; expression[ c ] != '\0'; ++c )
{
if ( islower( expression[ c ] ))
{
tbuf[ c ] = toupper( expression[ c ] );
}
else
{
tbuf[ c ] = expression[ c ];
}
tbuf[ c + 1 ] = '\0';
}
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isop(): expression is <%s>", tbuf );
bwb_debug( bwb_ebuf );
#endif
/* compare the initial characters of the string with the table
of operators */
for ( c = 0; c < N_OPERATORS; ++c )
{
if ( strncmp( tbuf, exp_ops[ c ].symbol,
(size_t) strlen( exp_ops[ c ].symbol ) ) == 0 )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isop(): match <%s>, number <%d>.",
exp_ops[ c ].symbol, c );
bwb_debug( bwb_ebuf );
#endif
return exp_ops[ c ].operation;
}
}
/* search failed; return OP_NULL */
return OP_NULL;
}
/***************************************************************
FUNCTION: exp_iscmd()
DESCRIPTION: This function reads the expression to find
if a BASIC command name is present; if so, it returns
OP_TERMINATE to terminate expression parsing. This is
critical, for example, in parsing a conditional following
IF where THEN, ELSE, and other BASIC commands may follow.
***************************************************************/
int
exp_iscmd( char *expression )
{
register int n;
char tbuf[ MAXSTRINGSIZE + 1 ];
/* capitalize the expression */
for ( n = 0; expression[ n ] != '\0'; ++n )
{
if ( n >= MAXARGSIZE )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Maximum arguments size exceeded." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_overflow );
#endif
}
if ( islower( expression[ n ] ) != FALSE )
{
tbuf[ n ] = toupper( expression[ n ] );
}
else
{
tbuf[ n ] = expression[ n ];
}
tbuf[ n + 1 ] = '\0';
}
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_iscmd(): expression received <%s>, converted <%s>.",
expression, tbuf );
bwb_debug( bwb_ebuf );
#endif
/* first check for THEN or ELSE statements */
if ( strcmp( tbuf, "THEN" ) == 0 )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
tbuf );
bwb_debug( bwb_ebuf );
#endif
return OP_TERMINATE;
}
if ( strcmp( tbuf, "ELSE" ) == 0 )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
tbuf );
bwb_debug( bwb_ebuf );
#endif
return OP_TERMINATE;
}
/* run through the command table and search for a match */
for ( n = 0; n < COMMANDS; ++n )
{
if ( strcmp( tbuf, bwb_cmdtable[ n ].name ) == 0 )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
tbuf );
bwb_debug( bwb_ebuf );
#endif
return OP_TERMINATE;
}
#if INTENSIVE_DEBUG
else
{
sprintf( bwb_ebuf, "in exp_iscmd(): No match, <%s> and <%s>; returns %d",
tbuf, bwb_cmdtable[ n ].name,
strcmp( tbuf, bwb_cmdtable[ n ].name ) );
bwb_debug( bwb_ebuf );
}
#endif
}
/* search failed, return NULL */
return OP_NULL;
}
/***************************************************************
FUNCTION: exp_isfn()
DESCRIPTION: This function reads the expression to find
if a function name is present at this point.
***************************************************************/
int
exp_isfn( char *expression )
{
if ( fnc_find( expression ) == NULL )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isfn(): failed to find function <%s>",
expression );
bwb_debug( bwb_ebuf );
#endif
return OP_NULL;
}
else
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isfn(): found function <%s>",
expression );
bwb_debug( bwb_ebuf );
#endif
return FUNCTION;
}
}
/***************************************************************
FUNCTION: exp_isvn()
DESCRIPTION: This function reads the expression to find
if a variable name at this point.
***************************************************************/
int
exp_isvn( char *expression )
{
exp_getvfname( expression, exp_es[ exp_esc ].string );
if ( var_find( exp_es[ exp_esc ].string ) == NULL )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isvn(): failed to find variable <%s>",
expression );
bwb_debug( bwb_ebuf );
#endif
return OP_NULL;
}
else
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_isvn(): found variable <%s>",
exp_es[ exp_esc ].string );
bwb_debug( bwb_ebuf );
#endif
return VARIABLE;
}
}
/***************************************************************
FUNCTION: exp_getvfname()
DESCRIPTION: This function reads the expression to find
a variable or function name at this point.
***************************************************************/
int
exp_getvfname( char *source, char *destination )
{
int s_pos, d_pos; /* source, destination positions */
s_pos = d_pos = 0;
destination[ 0 ] = '\0';
while( source[ s_pos ] != '\0' )
{
/* all aphabetical characters are acceptable */
if ( isalpha( source[ s_pos ] ) != 0 )
{
destination[ d_pos ] = source[ s_pos ];
++d_pos;
++s_pos;
destination[ d_pos ] = '\0';
}
/* numerical characters are acceptable but not in the first position */
else if (( isdigit( source[ s_pos ] ) != 0 ) && ( d_pos != 0 ))
{
destination[ d_pos ] = source[ s_pos ];
++d_pos;
++s_pos;
destination[ d_pos ] = '\0';
}
/* other characters will have to be tried on their own merits */
else
{
switch( source[ s_pos ] )
{
case '.': /* tolerated non-alphabetical characters */
case '_':
destination[ d_pos ] = source[ s_pos ];
++d_pos;
++s_pos;
destination[ d_pos ] = '\0';
break;
case STRING: /* terminating characters */
case SINGLE:
case DOUBLE:
case INTEGER:
destination[ d_pos ] = source[ s_pos ];
++d_pos;
++s_pos;
destination[ d_pos ] = '\0';
return TRUE;
default: /* anything else is non-tolerated */
return FALSE;
}
}
}
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getvfname(): found name <%s>", destination );
bwb_debug( bwb_ebuf );
#endif
return TRUE; /* exit after coming to the end */
}
/***************************************************************
FUNCTION: exp_validarg()
DESCRIPTION: This function reads the expression to
determine whether it is a valid argument (to be
read recursively by bwb_exp() and passed to a
function.
***************************************************************/
int
exp_validarg( char *expression )
{
register int c;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_validarg(): expression <%s>.",
expression );
bwb_debug( bwb_ebuf );
#endif
c = 0;
while ( TRUE )
{
switch( expression[ c ] )
{
case ' ':
case '\t':
++c;
break;
case '\0':
return FALSE;
default:
return TRUE;
}
}
}
/***************************************************************
FUNCTION: exp_getdval()
DESCRIPTION:
***************************************************************/
double
exp_getdval( struct exp_ese *e )
{
/* check for variable */
if ( e->operation == VARIABLE )
{
switch( e->type )
{
case DOUBLE:
return (* var_finddval( e->xvar, e->array_pos ));
case SINGLE:
return (double) (* var_findfval( e->xvar, e->array_pos ));
case INTEGER:
return (double) (* var_findival( e->xvar, e->array_pos ));
default:
bwb_error( err_mismatch );
return (double) 0.0;
}
}
/* must be a numerical value */
if ( e->operation != NUMBER )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getdval(): operation <%d> is not a number",
e->operation );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return (double) 0.0;
}
/* return specific values */
switch( e->type )
{
case SINGLE:
return (double) e->fval;
case INTEGER:
return (double) e->ival;
case DOUBLE:
return e->dval;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getdval(): type is <%c>",
e->type );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return (double) 0.0;
}
}
/***************************************************************
FUNCTION: exp_getfval()
DESCRIPTION:
***************************************************************/
float
exp_getfval( struct exp_ese *e )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getfval(): entry" );
bwb_debug( bwb_ebuf );
#endif
/* check for variable */
if ( e->operation == VARIABLE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
bwb_debug( bwb_ebuf );
#endif
switch( e->type )
{
case DOUBLE:
return (float) (* var_finddval( e->xvar, e->array_pos ));
case SINGLE:
return (* var_findfval( e->xvar, e->array_pos ));
case INTEGER:
return (float) (* var_findival( e->xvar, e->array_pos ));
default:
bwb_error( err_mismatch );
return (float) 0.0;
}
}
/* must be a numerical value */
if ( e->operation != NUMBER )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getfval(): operation <%d> is not a number",
e->operation );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return (float) 0.0;
}
/* return specific values */
switch( e->type )
{
case SINGLE:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getfval(): returning from SINGLE, val <%f>",
e->fval );
bwb_debug( bwb_ebuf );
#endif
return e->fval;
case INTEGER:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getfval(): returning from INTEGER, val <%d>",
e->ival );
bwb_debug( bwb_ebuf );
#endif
return (float) e->ival;
case DOUBLE:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getfval(): returning from DOUBLE, val <%lf>",
e->dval );
bwb_debug( bwb_ebuf );
#endif
return (float) e->dval;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getfval(): type is <%c>",
e->type );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return (float) 0.0;
}
}
/***************************************************************
FUNCTION: exp_getival()
DESCRIPTION:
***************************************************************/
int
exp_getival( struct exp_ese *e )
{
/* check for variable */
if ( e->operation == VARIABLE )
{
switch( e->type )
{
case DOUBLE:
return (int) (* var_finddval( e->xvar, e->array_pos ));
case SINGLE:
return (int) (* var_findfval( e->xvar, e->array_pos ));
case INTEGER:
return (* var_findival( e->xvar, e->array_pos ));
default:
bwb_error( err_mismatch );
return 0;
}
}
/* must be a numerical value */
if ( e->operation != NUMBER )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getival(): operation <%d> is not a number",
e->operation );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return 0;
}
/* return specific values */
switch( e->type )
{
case SINGLE:
return (int) e->fval;
case INTEGER:
return e->ival;
case DOUBLE:
return (int) e->dval;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getival(): type is <%c>",
e->type );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return 0;
}
}
/***************************************************************
FUNCTION: exp_getsval()
DESCRIPTION:
***************************************************************/
bstring *
exp_getsval( struct exp_ese *e )
{
static bstring b;
#if TEST_BSTRING
static int init = FALSE;
if ( init == FALSE )
{
sprintf( b.name, "<exp_getsval() bstring>" );
}
#endif
b.rab = FALSE;
/* return based on operation type */
switch( e->operation )
{
case CONST_STRING:
case OP_STRJOIN:
return &( e->sval );
case VARIABLE:
switch( e->type )
{
case STRING:
return var_findsval( e->xvar, e->array_pos );
case DOUBLE:
sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
str_ctob( &b, bwb_ebuf );
return &b;
case SINGLE:
sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
str_ctob( &b, bwb_ebuf );
return &b;
case INTEGER:
sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
str_ctob( &b, bwb_ebuf );
return &b;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
e->type );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return NULL;
}
break;
case NUMBER:
switch( e->type )
{
case DOUBLE:
sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
str_ctob( &b, bwb_ebuf );
return &b;
case SINGLE:
sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
str_ctob( &b, bwb_ebuf );
return &b;
case INTEGER:
sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
str_ctob( &b, bwb_ebuf );
return &b;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
e->type );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return NULL;
}
break;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_getsval(): operation <%d> inappropriate",
e->operation );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return NULL;
}
/* this point may not be reached */
return NULL;
}
/***************************************************************
FUNCTION: exp_findfval()
DESCRIPTION:
***************************************************************/
#ifdef NO_LONGER_IMPLEMENTED
float *
exp_findfval( struct exp_ese *e )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_findfval(): entry" );
bwb_debug( bwb_ebuf );
#endif
/* check for variable */
if ( e->operation == VARIABLE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
bwb_debug( bwb_ebuf );
#endif
return var_findfval( e->xvar, e->xvar->array_pos );
}
/* must be a numerical value */
if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_findfval(): operation is not a single-precision number" );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return NULL;
}
/* return specific value */
return &( e->fval );
}
/***************************************************************
FUNCTION: exp_finddval()
DESCRIPTION:
***************************************************************/
double *
exp_finddval( struct exp_ese *e )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_finddval(): entry" );
bwb_debug( bwb_ebuf );
#endif
/* check for variable */
if ( e->operation == VARIABLE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getdval(): returning variable" );
bwb_debug( bwb_ebuf );
#endif
return var_finddval( e->xvar, e->xvar->array_pos );
}
/* must be a numerical value */
if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_finddval(): operation is not a double-precision number" );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return NULL;
}
/* return specific value */
return &( e->dval );
}
/***************************************************************
FUNCTION: exp_findival()
DESCRIPTION:
***************************************************************/
int *
exp_findival( struct exp_ese *e )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_findival(): entry" );
bwb_debug( bwb_ebuf );
#endif
/* check for variable */
if ( e->operation == VARIABLE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_getival(): returning variable" );
bwb_debug( bwb_ebuf );
#endif
return var_findival( e->xvar, e->xvar->array_pos );
}
/* must be a numerical value */
if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in exp_findival(): operation is not an integer number" );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return NULL;
}
/* return specific value */
return &( e->ival );
}
#endif
/***************************************************************
FUNCTION: inc_esc()
DESCRIPTION: This function increments the expression
stack counter.
***************************************************************/
int
inc_esc( void )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in inc_esc(): prev level <%d>",
exp_esc );
bwb_debug ( bwb_ebuf );
#endif
++exp_esc;
if ( exp_esc >= ESTACKSIZE )
{
--exp_esc;
#if PROG_ERRORS
sprintf( bwb_ebuf, "in inc_esc(): Maximum expression stack exceeded <%d>",
exp_esc );
bwb_error( bwb_ebuf );
#else
bwb_error( err_overflow );
#endif
return OP_NULL;
}
#if INTENSIVE_DEBUG
sprintf( exp_es[ exp_esc ].string, "New Expression Stack Level %d", exp_esc );
#endif
exp_es[ exp_esc ].type = INTEGER;
exp_es[ exp_esc ].operation = OP_NULL;
exp_es[ exp_esc ].pos_adv = 0;
return TRUE;
}
/***************************************************************
FUNCTION: dec_esc()
DESCRIPTION: This function decrements the expression
stack counter.
***************************************************************/
int
dec_esc( void )
{
--exp_esc;
if ( exp_esc < 0 )
{
exp_esc = 0;
#if PROG_ERRORS
sprintf( bwb_ebuf, "in dec_esc(): Expression stack counter < 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_overflow );
#endif
return OP_NULL;
}
return TRUE;
}